﻿using PmSoft.Web.Abstractions.ErrorCode;
using System.Text.Json.Serialization;

namespace PmSoft.Web.Abstractions;

// <summary>
/// 定义 API 响应结果的基本结构，用于标准化业务操作返回数据的格式。
/// </summary>
public interface IApiResult
{
	/// <summary>
	/// 表示业务操作是否成功。
	/// </summary>
	bool Success { get; set; }

	/// <summary>
	/// 业务状态码，用于标识操作结果。例如，"SUCCESS" 表示成功，"USER_NOT_FOUND" 表示用户不存在。
	/// </summary>
	string? Code { get; set; }

	/// <summary>
	/// 业务消息，用于描述操作结果或错误原因。
	/// </summary>
	string? Msg { get; set; }

	/// <summary>
	/// 响应时间戳，表示从 1970-01-01 00:00:00 UTC 开始的毫秒数。
	/// </summary>
	long Timestamp { get; set; }
}

/// <summary>
/// 泛型 API 响应结果类，用于封装业务操作的返回数据，遵循 RESTful API 设计最佳实践。
/// </summary>
/// <typeparam name="T">业务数据的类型，可以是任意对象或集合。</typeparam>
public class ApiResult<T> : IApiResult
{
	/// <summary>
	/// 表示业务操作是否成功。
	/// </summary>
	[JsonPropertyName("success")]
	public bool Success { get; set; }

	/// <summary>
	/// 业务状态码，用于标识操作结果。例如，"SUCCESS" 表示成功，"USER_NOT_FOUND" 表示用户不存在。
	/// </summary>
	[JsonPropertyName("code")]
	public string? Code { get; set; } = "SUCCESS";

	/// <summary>
	/// 业务消息，用于描述操作结果或错误原因。
	/// </summary>
	[JsonPropertyName("msg")]
	public string? Msg { get; set; }

	/// <summary>
	/// 业务数据，成功时携带返回数据，失败时可能包含错误详情或元数据。
	/// </summary>
	[JsonPropertyName("data")]
	public T? Data
	{
		get => _data;
		set => _data = value;
	}
	private T? _data;

	/// <summary>
	/// 响应时间戳，表示从 1970-01-01 00:00:00 UTC 开始的毫秒数，默认值为当前 UTC 时间。
	/// </summary>
	[JsonPropertyName("timestamp")]
	public long Timestamp { get; set; } = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();

	/// <summary>
	/// 创建一个表示成功的 API 响应结果，仅包含业务消息。
	/// </summary>
	/// <param name="msg">业务消息，用于描述操作成功的详情。</param>
	/// <returns>一个成功的 <see cref="ApiResult{T}"/> 实例。</returns>
	public static ApiResult<T> Ok(string msg)
	{
		return new ApiResult<T> { Success = true, Msg = msg, Code = "SUCCESS" };
	}

	/// <summary>
	/// 创建一个表示成功的 API 响应结果，包含业务数据。
	/// </summary>
	/// <param name="data">业务数据，返回给客户端的具体结果。</param>
	/// <returns>一个成功的 <see cref="ApiResult{T}"/> 实例。</returns>
	public static ApiResult<T> Ok(T? data)
	{
		return new ApiResult<T> { Success = true, Data = data, Code = "SUCCESS" };
	}

	/// <summary>
	/// 创建一个表示失败的 API 响应结果，包含业务数据。
	/// </summary>
	/// <param name="data">业务数据，可用于返回失败时的附加信息（如错误详情）。</param>
	/// <param name="code">业务状态码，表示具体的失败原因，默认为 null。</param>
	/// <returns>一个失败的 <see cref="ApiResult{T}"/> 实例。</returns>
	public static ApiResult<T> Error(T? data, string? code = null)
	{
		return new ApiResult<T> { Success = false, Code = code, Data = data };
	}

	/// <summary>
	/// 创建一个表示失败的 API 响应结果，仅包含业务消息。
	/// </summary>
	/// <param name="msg">业务消息，用于描述操作失败的原因。</param>
	/// <param name="code">业务状态码，表示具体的失败原因，默认为 null。</param>
	/// <returns>一个失败的 <see cref="ApiResult{T}"/> 实例。</returns>
	public static ApiResult<T> Error(string msg, string? code = null)
	{
		return new ApiResult<T> { Msg = msg, Code = code, Success = false };
	}
}

/// <summary>
/// 非泛型 API 响应结果类，继承自 <see cref="ApiResult{object}"/>，用于简化无具体数据类型的场景。
/// </summary>
public class ApiResult : ApiResult<object>
{
	/// <summary>
	/// 创建一个表示成功的 API 响应结果，仅包含业务消息。
	/// </summary>
	/// <param name="msg">业务消息，用于描述操作成功的详情。</param>
	/// <returns>一个成功的 <see cref="ApiResult"/> 实例。</returns>
	public new static ApiResult Ok(string msg)
	{
		return new ApiResult
		{
			Code = "SUCCESS",
			Msg = msg,
			Success = true
		};
	}

	/// <summary>
	/// 创建一个表示失败的 API 响应结果，仅包含业务消息。
	/// </summary>
	/// <param name="msg">业务消息，用于描述操作失败的原因。</param>
	/// <returns>一个失败的 <see cref="ApiResult"/> 实例，默认使用 "BUSINESS_ERROR" 状态码。</returns>
	public static ApiResult Error(string msg)
	{
		var error = ErrorCodeManager.GetError("BUSINESS_ERROR");
		return new ApiResult
		{
			Msg = msg,
			Code = error.Code,
			Success = false
		};
	}

	/// <summary>
	/// 创建一个表示失败的 API 响应结果，基于指定的业务状态码。
	/// </summary>
	/// <param name="code">业务状态码，用于标识具体的失败原因。</param>
	/// <param name="msg">业务消息，用于描述操作失败的原因，若为空则使用状态码对应的默认消息。</param>
	/// <returns>一个失败的 <see cref="ApiResult"/> 实例。</returns>
	public new static ApiResult Error(string code, string? msg = null)
	{
		var error = ErrorCodeManager.GetError(code); // 从错误码管理器获取定义
		return new ApiResult
		{
			Code = error.Code,
			Success = false,
			Msg = msg ?? error.Message
		};
	}
}